
package.cpath = ";;./?.dll;./clib/?.dll;"
package.path = "./lualib/?/init.lua;./lualib/?.lua;"

local _G = _G;


require 'wx'
require 'lfs'
require 'lsqlite3'
require 'barf'


-- Set up helper function to allocate IDs
local lastID = wx.wxID_HIGHEST;
local function nextID()
    lastID = lastID + 1;
    return lastID;
end
_G.nextID = nextID;

-- Main window
local mainWindow = wx.wxFrame(
	wx.NULL,
	wx.wxID_ANY,
	"BARF! v0.2",
	wx.wxDefaultPosition,
	wx.wxSize(450, 450),
	wx.wxDEFAULT_FRAME_STYLE);
_G.mainWindow = mainWindow;
mainWindow.Sizer = wx.wxBoxSizer(wx.wxVERTICAL);

-- Icon
do
    local barfIcon = wx.wxIcon();
    barfIcon:CopyFromBitmap(wx.wxBitmap("alex.png"));
    mainWindow.Icon = barfIcon;
end

-- Status bar
local statusBar = mainWindow:CreateStatusBar(1) do
	mainWindow.StatusText = "The ROM HACKERS' turf!";
end
_G.statusBar = statusBar;

-- Main panel
local mainPanel = wx.wxPanel(
    mainWindow,
    wx.wxID_ANY);
mainPanel.Sizer = wx.wxBoxSizer(wx.wxVERTICAL);
mainPanel:Hide();
mainWindow.Sizer:Add(mainPanel, 1, wx.wxEXPAND);
_G.mainPanel = mainPanel;

-- Editors notebook (tabbed view)
local editorsNotebook = wx.wxNotebook(
    mainPanel,
    wx.wxID_ANY,
    wx.wxDefaultPosition,
    wx.wxDefaultSize,
    wx.wxNB_NOPAGETHEME);
mainPanel.Sizer:Add(editorsNotebook, 1, wx.wxEXPAND);
local function initEditorPage()
    local page = wx.wxPanel(
        editorsNotebook,
        wx.wxID_ANY);
    page:Hide();
    return page;
end
local function addEditorPage(page, title)
    editorsNotebook:AddPage(page, title, true);
    page:Show(true);
    mainPanel:Show(true);
    mainWindow:Layout();
end

-- Finalize main panel layout
mainPanel:Layout();

-- Finalize main window layout
mainWindow:Layout();

-- Menu bar
mainWindow.MenuBar = wx.wxMenuBar();

-- File menu
do
    local fileMenu = wx.wxMenu{
        {wx.wxID_OPEN,  "&Open ROM...",   "Open a River City Ransom ROM for editing"},
        {},
        {wx.wxID_SAVE,	"&Save\tCtrl-S",  "Save the currently opened ROM"},
        {wx.wxID_SAVEAS,"Save &as...",    "Save the ROM to a new location"},
        {},
        {wx.wxID_EXIT,  "E&xit",          "Quit BARF!"}
    };
    
    mainWindow:Connect(wx.wxID_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local openDialog = wx.wxFileDialog(mainWindow,
                "Choose a ROM", "", "",
                "NES ROM images (*.nes)|*.nes",
                wx.wxOPEN + wx.wxFILE_MUST_EXIST);
            if (openDialog:ShowModal() == wx.wxID_CANCEL) then
                return;
            end
            local romfile = assert(io.open(openDialog.Path, 'rb'));
            local loadedrom, message = barf.nes.readrom(romfile);
            romfile:close();
            if not loadedrom then
                error(message);
            end
            loadedrom.path = openDialog.Path;
            loadedrom.romlib = barf.rcr;
            _G.rom = loadedrom;
            mainWindow.StatusText = "Loaded \"" .. (loadedrom.title or openDialog.Path) .. "\"";
        end);
        
    mainWindow:Connect(wx.wxID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then
                return;
            end
            local romfile = assert(io.open(rom.path, 'wb'));
            barf.nes.saverom(romfile, rom);
            romfile:close();
            mainWindow.StatusText = "Saved to " .. rom.path;
        end);
    
    mainWindow:Connect(wx.wxID_SAVEAS, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then
                return;
            end
            local saveDialog = wx.wxFileDialog(mainWindow,
                "Save as...", "", "",
                "NES ROM images (*.nes)|*.nes",
                wx.wxSAVE + wx.wxOVERWRITE_PROMPT);
            if (saveDialog:ShowModal() == wx.wxID_CANCEL) then
                return;
            end
            rom.path = saveDialog.Path;
            mainWindow:ProcessEvent(
                wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, wx.wxID_SAVE)
            );
        end);
    
    mainWindow:Connect(wx.wxID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            mainWindow.Visible = false;
            mainWindow:Close(true);
        end);
    
    mainWindow.MenuBar:Append(fileMenu, "&File");
end

-- Editors menu
local editorsMenu = wx.wxMenu() do
    local ID_EDITOR_SHOPITEM = nextID();
    local ID_EDITOR_STOCKLIST = nextID();
    local ID_EDITOR_NPCNAMES = nextID();
    local ID_EDITOR_NPCCONVO = nextID();
    local ID_EDITOR_SHOPCONVO = nextID();
    local ID_EDITOR_SHOPACTIONS = nextID();
    local ID_EDITOR_SHOPSUBMENUS = nextID();
    
    editorsMenu:Append(wx.wxID_ANY, "&Text Editors", wx.wxMenu{
        {ID_EDITOR_NPCNAMES,    "NPC Names",         "Edit the names of gang members, bosses, and friends"},
        {ID_EDITOR_NPCCONVO,    "NPC Conversation",
            "Edit speech by gang members, bosses and friends, and also gang turf names"},
        {ID_EDITOR_SHOPCONVO,   "Shop Conversation", "Edit speech by shop owners"},
        {ID_EDITOR_SHOPACTIONS, "Item Actions, Location Names && Game Screens",
            "Edit the text for using inventory items, the names of locations, and more"},
        {ID_EDITOR_SHOPSUBMENUS,"Shop Submenus",     "Edit the names of submenus used in some shops"},
    });
    
    local experimentalMenu = wx.wxMenu();
    
    experimentalMenu:Append(ID_EDITOR_SHOPITEM, "Shop Items",
        "Edit the name, price and stat increases for shop items");
    experimentalMenu:Append(ID_EDITOR_STOCKLIST, "Stock Lists",
        "Edit the list of items that shops have for sale");
    
    editorsMenu:Append(wx.wxID_ANY, "Incomplete/WIP", experimentalMenu);
    
    mainWindow:Connect(ID_EDITOR_NPCNAMES, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then  return;  end
            local editorPage = initEditorPage();
            barf.editors.text(rom.romlib.addresses.npcs.names, editorPage);
            addEditorPage(editorPage, "NPC Names");
        end);
    
    mainWindow:Connect(ID_EDITOR_NPCCONVO, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then  return;  end
            local editorPage = initEditorPage();
            barf.editors.text(rom.romlib.addresses.npcs.conversation, editorPage);
            addEditorPage(editorPage, "NPC Speech");
        end);
    
    mainWindow:Connect(ID_EDITOR_SHOPCONVO, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then  return;  end
            local editorPage = initEditorPage();
            barf.editors.text(rom.romlib.addresses.shops.conversation, editorPage);
            addEditorPage(editorPage, "Shop Speech");
        end);
    
    mainWindow:Connect(ID_EDITOR_SHOPACTIONS, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then  return;  end
            local editorPage = initEditorPage();
            barf.editors.text(rom.romlib.addresses.shops.actions, editorPage);
            addEditorPage(editorPage, "Actions/Locations");
        end);
    
    mainWindow:Connect(ID_EDITOR_SHOPSUBMENUS, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then  return;  end
            local editorPage = initEditorPage();
            barf.editors.text(rom.romlib.addresses.shops.submenus, editorPage);
            addEditorPage(editorPage, "Shop Submenus");
        end);
    
    mainWindow:Connect(ID_EDITOR_SHOPITEM, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then  return;  end
            local editorPage = initEditorPage();
            barf.editors.shopitem(rom.romlib.addresses.shops.items, editorPage);
            addEditorPage(editorPage, "Shop Items");
        end);
    
    mainWindow:Connect(ID_EDITOR_STOCKLIST, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            local rom = _G.rom;
            if not rom then  return;  end
            local editorPage = initEditorPage();
            barf.editors.shopstock(rom.romlib.addresses.shops.stock, editorPage);
            addEditorPage(editorPage, "Stock Lists");
        end);
    
    mainWindow.MenuBar:Append(editorsMenu, "&Editors");
end

-- Help menu
do
    local helpMenu = wx.wxMenu{
        {wx.wxID_ABOUT,  "&About...",    "About the editor"}
    };
    
    mainWindow:Connect(wx.wxID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED,
        function()
            wx.wxMessageBox(
                table.concat({
                    'BARF!',
                    '',
                    'Made with '..wxlua.wxLUA_VERSION_STRING..' / '..wx.wxVERSION_STRING
                },'\n'),
                "About BARF!",
                wx.wxOK + wx.wxICON_INFORMATION,
                mainWindow
            );
        end);
    
    mainWindow.MenuBar:Append(helpMenu, "&Help");
end	


-- Nothing left to do but show the main window

local App = wx.wxGetApp();

App:SetAppName("BARF!");

mainWindow:Show(true);
App:MainLoop();
